#!/home/cs1010/anaconda3/envs/mqtt_admin/bin/python

import time
import ssl
import paho.mqtt.client as mqtt
import configparser


class MQTTClientWrapper:
    def __init__(self, config_file):
        """
        初始化 MQTT 客户端实例。
        :param config_file: 配置文件路径
        """
        # 读取配置文件中的 MQTT 服务器信息
        self.mqtt_broker, self.mqtt_port, self.username, self.password = self.read_config(config_file)
        # 客户端 ID
        self.client_id = "python_publisher"
        # 设备注册的 MQTT 话题
        self.device_id_topic = "device/register"
        # 创建 MQTT 客户端实例
        self.client = self.setup_mqtt_client()
        # 标记是否正在运行，初始为 False
        self.is_running = False

    def read_config(self, config_file):
        """
        读取配置文件中的 MQTT 服务器信息。
        :param config_file: 配置文件路径
        :return: MQTT 服务器地址、端口、用户名和密码
        """
        # 创建配置解析器实例
        config = configparser.ConfigParser()
        # 读取配置文件
        config.read(config_file)
        # 获取 MQTT 配置部分
        mqtt_config = config['MQTT']
        # 获取 MQTT 服务器地址
        mqtt_broker = mqtt_config.get('broker')
        # 获取 MQTT 服务器端口
        mqtt_port = int(mqtt_config.get('port'))
        # 获取 MQTT 用户名
        username = mqtt_config.get('username')
        # 获取 MQTT 密码
        password = mqtt_config.get('password')
        return mqtt_broker, mqtt_port, username, password

    def setup_mqtt_client(self):
        """
        设置 MQTT 客户端，包括连接回调、消息回调、TLS 配置和用户名密码认证。
        :return: 配置好的 MQTT 客户端实例
        """
        # 创建 MQTT 客户端实例
        client = mqtt.Client(client_id=self.client_id)

        def on_connect(client, userdata, flags, rc):
            """
            连接成功时的回调函数，订阅设备注册话题。
            :param client: MQTT 客户端实例
            :param userdata: 用户数据
            :param flags: 连接标志
            :param rc: 连接结果码
            """
            if rc == 0:
                print("Connected to MQTT Broker!")
                # 订阅设备注册话题
                client.subscribe(self.device_id_topic)
            else:
                print(f"Failed to connect, return code {rc}")

        def on_message(client, userdata, msg):
            """
            接收到消息时的回调函数，处理设备 ID 消息。
            :param client: MQTT 客户端实例
            :param userdata: 用户数据
            :param msg: 接收到的消息
            """
            if msg.topic == self.device_id_topic:
                # 解码消息内容得到设备 ID
                device_id = msg.payload.decode()
                # 调用传入的回调函数处理设备 ID
                self.callback(device_id)

        # 设置连接成功回调函数
        client.on_connect = on_connect
        # 设置接收到消息回调函数
        client.on_message = on_message
        # 设置 TLS 配置，不验证证书
        client.tls_set(cert_reqs=ssl.CERT_NONE)
        # 允许不安全的 TLS 连接
        client.tls_insecure_set(True)
        # 设置用户名和密码
        client.username_pw_set(self.username, self.password)
        return client

    def connect_to_mqtt(self):
        """
        连接到 MQTT 服务器并启动循环处理消息。
        :return: 连接成功返回 True，失败返回 False
        """
        try:
            # 连接到 MQTT 服务器
            self.client.connect(self.mqtt_broker, self.mqtt_port)
            # 启动循环处理消息
            self.client.loop_start()
            return True
        except Exception as e:
            print(f"Connection error: {e}")
            return False

    def start_listening(self, callback):
        """
        开始监听设备 ID 消息。
        :param callback: 处理设备 ID 的回调函数
        """
        # 标记为正在运行
        self.is_running = True
        # 保存回调函数
        self.callback = callback
        while self.is_running:
            # 每隔 1 秒检查一次是否继续运行
            time.sleep(1)

    def stop_listening(self):
        """
        停止监听设备 ID 消息，停止循环并断开连接。
        """
        # 标记为停止运行
        self.is_running = False
        # 停止循环处理消息
        self.client.loop_stop()
        # 断开与 MQTT 服务器的连接
        self.client.disconnect()

    def publish_activation_code(self, device_id, activation_code):
        """
        发布激活码给指定设备。
        :param device_id: 设备 ID
        :param activation_code: 激活码
        """
        # 生成设备专属的激活话题
        activation_topic = f"device/{device_id}/activation"
        # 发布激活码到指定话题
        self.client.publish(activation_topic, activation_code)
        print(f"Sent activation code {activation_code} to device {device_id}")
    